import {
    autorun,
    computed,
    observable,
    reaction,
    when
} from 'mobx'

class Store {
    @observable array = [];
    @observable obj = {};
    @observable map = new Map();
    // 会自动识别，不用手动区分可观察还是间接观察
    @observable string = 'hello';
    @observable number = 20;
    @observable bool = false;

    @computed get mixed() {
        return store.string + '/' + store.number + '/'
    }
}

// computed
// 将其他可观察数据以用户想要的方式组合起来变成一个新的可观察数据
const store = new Store();

// const computedString = computed(function () {
//     return store.string + '/' + store.number + '/'
// })

// // console.log(computedString); // ComputedValue 对象
// // console.log(computedString.get()); // hello/20/

// // 为了观察到 computedString 的变化，需要使用 observe 方法
// // 需要函数入参，change存储了修改前后变量的值
// computedString.observe(function (change) {
//     console.log(change.newValue);
// })

// store.string = 'world'
// // string发生了变化：world/20/
// store.number = 30
// // number发生了变化：world/30/

// // console.log(computedString.get());

// autorun
// autorun自动运行传到autorun的函数
// autorun(() => {
//     console.log(store.string + '/' + store.number + '/');
//     // 自动会执行里面的内容
//     // 
//     // console.log(store.mixed);
//     // 和上面效果一致
//     // 证明 computed 值可以作为一个可观察值看待的
// })
// // 修改 autorun 中的任意可观察数据可以自动运行autorun中的内容
// // 总共打印三次：hello/20/ world/20/ world/30/
// store.string = 'world'
// // string发生了变化：world/20/
// store.number = 30
// // number发生了变化：world/30/

// // when
// // 用法：接收两个函数参数，第一个函数参数根据可观察函数参数返回的布尔值来决定第二个函数是否执行，并执行一次
// when(() => store.bool, () => console.log("it's true"))

// store.bool = true
// // 因此将bool修改为 true 后，才打印 "it's true"
// // 
// // 注意1：必须根据可观察数据来判断，不能引用其他变量
// // 下面两行不会打印
// when(() => !!store.bar, () => console.log("it's true"))

// store.bar = true
// // 
// // 注意2：如果一开始里面就是真的话，就会同步执行代码
// // 此时 store.bool 为 true
// console.log('before');
// when(() => store.bool, () => console.log("it's true"))
// console.log('after');
// // 以此打印 before it's true after

// reaction
// 用法：接收两个函数类型的参数，第一个函数也用可观察数据并返回一个值，这个值会作为第二个值的参数
reaction(() => [store.string, store.number], arr => console.log(arr.join('/')))
store.string = 'world'
// string发生了变化：world/20/
store.number = 30
// number发生了变化：world/30/
// 使用场景：在没有数据之前，我们不想也没有必要调用写缓存的逻辑，可以用reaction实现在数据被第一次填充之后才启   动写缓存逻辑